﻿; (function ($) {
    var borderColor = ui.theme.Classes.BorderHighlight,
        bgColor = ui.theme.Classes.BackgroundHighlight,
        fontColor = ui.theme.Classes.FontHighlight;

    /// form 表单元素
    var checkboxDisabled = "input-checkbox-disabled",
        radioChecked = "input-radio-checked",
        radioDisabled = "input-radio-disabled";

    var normalCheckboxLabel = "<label class='input-checkbox' />",
        checkedCheckboxLabel = "<label class='input-checkbox input-checkbox-checked' />",
        normalRadioLabel = "<label class='input-radio' />",
        checkedRadioLabel = "<label class='input-radio input-radio-checked' />";

    //checkbox
    var checkButton = function () {
    };
    checkButton.prototype = {
        warpCheckBox: function (cbx) {
            if (cbx.prop("checked")) {
                cbx.wrap(checkedCheckboxLabel);
            } else {
                cbx.wrap(normalCheckboxLabel);
            }

            cbx.change($.proxy(this.changeHandler, this));
        },
        changeHandler: function (e) {
            var checkbox = $(e.target);
            this.setCheckedChange(checkbox);
        },
        setCheckedChange: function (checkbox) {
            var label = checkbox.parent();
            if (checkbox.prop("checked")) {
                label.addClass("input-checkbox-checked");
            } else {
                label.removeClass("input-checkbox-checked");
            }
        }
    };

    //rediobutton
    var defaultRadioName = "undefined";
    var radioButton = function () {
        this.radios = {};
    };
    radioButton.prototype = {
        warpRadioButton: function (rdo) {
            var name = rdo.prop("name");
            if (!name || name.length == 0) {
                name = defaultRadioName;
            }
            var arr;
            if (this.radios.hasOwnProperty(name)) {
                arr = this.radios[name];
            } else {
                arr = [];
                this.radios[name] = arr;
            }
            if (rdo.prop("checked")) {
                rdo.wrap(checkedRadioLabel);
                this.currentRadio = rdo;
            } else {
                rdo.wrap(normalRadioLabel);
            }
            arr.push(rdo);
            rdo.change($.proxy(this.changeHandler, this));
        },
        changeHandler: function (e) {
            var rdo = $(e.target);
            this.setCheckedChange(rdo);
        },
        setCheckedChange: function (rdo) {
            var name = rdo.prop("name");
            var arr, label, i = 0;
            if (!name || name.length == 0) {
                name = defaultRadioName;
            }
            arr = this.radios[name];
            for (; i < arr.length; i++) {
                label = arr[i].parent();
                if (label.hasClass(radioChecked)) {
                    label.removeClass(radioChecked);
                    break;
                }
            }

            label = rdo.parent();
            if (rdo.prop("checked")) {
                label.addClass(radioChecked);
            } else {
                label.removeClass(radioChecked);
            }
        }
    };

    var cbxBtn = new checkButton();
    var rdoBtn = new radioButton();

    $.fn.metroCheckbox = function () {
        if (this.length == 0) {
            return;
        }
        if (this.length == 1) {
            cbxBtn.warpCheckBox(this);
        } else {
            var i = 0;
            for (; i < this.length; i++) {
                cbxBtn.warpCheckBox($(this[i]));
            }
        }
        return this;
    };

    $.fn.setMCChecked = function (checked) {
        var val = this.prop("checked");
        if (val != checked) {
            this.prop("checked", !val);
            cbxBtn.setCheckedChange(this);
        }
    };

    $.fn.metroRadio = function () {
        if (this.length == 0) {
            return;
        }
        if (this.length == 1) {
            rdoBtn.warpRadioButton(this);
        } else {
            var i = 0;
            for (; i < this.length; i++) {
                rdoBtn.warpRadioButton($(this[i]));
            }
        }
        return this;
    };

    $.fn.setMRChecked = function (checked) {
        var val = this.prop("checked");
        if (val != checked) {
            this.prop("checked", !val);
            rdoBtn.setCheckedChange(this);
        }
    };

    //switchbutton
    var switchButtonClass = "switch-button",
        switchBorderClass = "switch-border",
        switchThumbClass = "switch-thumb",
        switchThumbOnClass = "switch-thumb-on",
        switchInnerClass = "switch-inner",
        switchInnerOnClass = "switch-inner-on",
        switchCheckboxClass = "switch-checkbox";

    var optionKey = "option";

    var switchButton = function () {
        this.tiles = null;
        this.tilePanel = null;
    };
    switchButton.prototype = {
        createSwitchButton: function (option) {
            var button = $("<div class='" + switchButtonClass + "' />");
            if (option.id)
                button.prop("id", option.id);
            var cbx = $("<input type='checkbox' class='" + switchCheckboxClass + "' >");
            if (option.value && option.value.length > 0)
                cbx.prop("value", option.value);
            option.checked = !!option.checked;
            cbx.prop("checked", option.checked);

            button.append(cbx);
            return this._buttonInit(button, cbx, option);
        },
        initSwitchButton: function (cbx, option) {
            var button = $("<div class='" + switchButtonClass + "' />");
            var id = cbx.prop("id");
            if (!option)
                option = {};
            if (id.length > 0) {
                button.prop("id", "switch_" + id);
                option.id = id;
            }
            if (!cbx.hasClass(switchCheckboxClass)) {
                cbx.addClass(switchCheckboxClass);
            }
            cbx.wrap(button);
            button = cbx.parent();
            option.checked = cbx.prop("checked");
            option.value = cbx.val();
            this._buttonInit(button, cbx, option);
        },
        _buttonInit: function (button, cbx, option) {
            var border = $("<div class='" + switchBorderClass + "' />");
            var inner = $("<div class='" + switchInnerClass + "' />");
            var thumb = $("<div class='" + switchThumbClass + "'>");

            if (option.checked) {
                inner.addClass(switchInnerOnClass).addClass(bgColor);
                thumb.addClass(switchThumbOnClass);
            }

            border.append(inner);
            button.append(border);
            button.append(thumb);

            button.data(optionKey, option);
            button.click($.proxy(this.onClick, this));
            cbx.change($.proxy(this.onChange, this));
            cbx.click($.proxy(this.onCheckboxClick, this));

            return button;
        },
        setChecked: function (elem, checked) {
            if (!elem)
                return;
            checked = !!checked;
            if (elem.nodeName() === "INPUT")
                elem = elem.parent();
            var cbx = elem.find("input");

            cbx.prop("checked", checked);
            this.onChanged(elem, checked, cbx.val());
        },
        getChecked: function (elem) {
            if (!elem)
                return null;
            if (elem.nodeName() === "INPUT")
                return elem.prop("checked");
            var cbx = elem.find("input");
            if (cbx.length == 0)
                return null;
            return cbx.prop("checked");
        },
        onClick: function (e) {
            e.stopPropagation();

            var elem = $(e.target);
            var btn, cbx;
            while (!elem.hasClass(switchButtonClass)) {
                elem = elem.parent();
                if (elem.nodeName() === "BODY") {
                    return;
                }
            }

            cbx = elem.find("input");
            var checked = !cbx.prop("checked");
            cbx.prop("checked", checked);

            this.onChanged(elem, checked, cbx.val());
        },
        onChange: function (e) {
            var cbx = $(e.target);
            var btn = cbx.parent();

            this.onChanged(btn, cbx.prop("checked"), cbx.val());
        },
        onCheckboxClick: function (e) {
            e.stopPropagation();
        },
        onChanged: function (elem, checked, value) {
            var inner, thumb;
            inner = elem.find("." + switchInnerClass);
            thumb = elem.find("." + switchThumbClass);

            option = elem.data(optionKey);
            if (!checked) {
                thumb.removeClass(switchThumbOnClass);
                inner.removeClass(switchInnerOnClass).removeClass(bgColor);
            } else {
                thumb.addClass(switchThumbOnClass);
                inner.addClass(switchInnerOnClass).addClass(bgColor);
            }
            if (option && $.isFunction(option.changeHandler)) {
                option.changeHandler(elem, checked, value);
            }
        }
    };

    var switchBtn = new switchButton();
    ui.SwitchButton = {
        rander: function (option) {
            return switchBtn.createSwitchButton(option);
        },
        setChecked: function (elem, checked) {
            if (ui.core.type(elem) === "string") {
                elem = $("#" + elem);
            }
            switchBtn.setChecked(elem, checked);
        },
        getChecked: function (elem) {
            if (ui.core.type(elem) === "string") {
                elem = $("#" + elem);
            }
            return switchBtn.getChecked(elem);
        }
    };
    //option: id, value, checked, changeHandler: function(elem, checked)
    $.fn.switchButton = function (option) {
        if (!this || this.length == 0) {
            return this;
        }
        return this.each(function () {
            switchBtn.initSwitchButton($(this), option);
        });
    };

    ///表单折叠
    $.fn.foldPanel = function () {
        var dl = this;
        if (dl.length == 0)
            return;
        var dtList = dl.find("dt"),
            dt = null,
            text = "", div = null;
        for (var i = 0, l = dtList.length; i < l; i++) {
            dt = $(dtList[i]);
            text = dt.text();
            div = $("<div class='fold-close' />").addClass(borderColor);
            if (dt.next().css("display") === "none") {
                div.addClass(bgColor).text("+");
            } else {
                div.addClass(fontColor).text("-");
            }
            dt.html("");
            dt.append(div)
                .append($("<span />").text(text).addClass(fontColor));
            dt.click(foldTitleClick);
        }
    };

    var foldTitleClick = function (e) {
        var title = $(e.target);
        if (title.prop("tagName") === "DT")
            return;
        title = title.parent();
        var btn = $(title.find("div")[0]);
        var dd = title.next();
        if (dd.css("display") === "none") {
            btn.removeClass(bgColor).addClass(fontColor).text("-");
            dd.css("display", "block");
        } else {
            btn.removeClass(fontColor).addClass(bgColor).text("+");
            dd.css("display", "none");
        }
        e.stopPropagation();
    };

    ///form 表单编辑面板
    var leftBorderWidth = 4,
        contentTop = 40,
        buttonTop = 30,
        buttonPanelHeight = 48;

    var contentHeight = 0;

    //event type
    var showing = "showing",
        showed = "showed",
        hiding = "hiding",
        hided = "hided";

    var ctrlPanel = ui.define("ctrls.CtrlPanel", {
        _getCreateOption: function () {
            return {
                parent: null,
                width: 240
            };
        },
        _getEvents: function () {
            return [showing, showed, hiding, hided];
        },
        _create: function () {
            this.animating = false;
            this.isShow = false;
            var id;
            if (ui.core.type(this.option.parent) === "string") {
                id = this.option.parent;
                this.option.parent = $("#" + id);
                if (this.option.parent.length == 0) {
                    ui.error(id + " is not exists");
                }
            }
            this.parent = this.option.parent;
            this.panel = null;
            this.contentPanel = null;
            this.height = 0;
            this.width = $.isNumeric(this.option.width) ? this.option.width : 240;
            this.top = 0;
            this.left = 0;
        },
        _init: function () {
            this.panel = $("<div class='form-ctrl-panel' />").addClass(borderColor);
            this.panel.css("width", this.width + "px");

            this.contentPanel = $("<div class='ctrl-content-panel' />");
            this.panel.append(this.contentPanel);

            this.buttonPanel = $("<div class='ctrl-button-panel' />");
            this.panel.append(this.buttonPanel);

            var closeBtn = $("<a class='right' href='javascript:void(0)' />");
            var $this = this;
            closeBtn.click(function (e) {
                $this.hide();
            });
            this.panel.append(closeBtn);
            this.parent.append(this.panel);

            this._contentAppend(this.element);
        },
        setSizeLocation: function (width) {
            var parentWidth = this.parent.width();
            var parentHeight = this.parent.height();
            this.height = parentHeight;
            var sizeCss = {
                height: this.height + "px"
            };
            var right = this.width;
            if ($.isNumeric(width)) {
                this.width = width;
                sizeCss["width"] = this.width + "px";
                right = width;
            }
            this.hideLeft = parentWidth;
            this.left = parentWidth - this.width - leftBorderWidth;
            this.panel.css(sizeCss);
            var contentMaxheight = this.height - contentTop - buttonTop - buttonPanelHeight;
            this.contentPanel.css({
                "max-height": contentMaxheight + "px"
            });
            if (contentMaxheight < contentHeight) {
                this.buttonPanel.css("width", this.width - 17 + "px");
            } else {
                this.buttonPanel.css("width", "100%");
            }
            if (!this.isShow) {
                this.panel.css({
                    "left": this.hideLeft + "px",
                    "display": "none"
                });
            } else {
                this.panel.css({
                    "left": this.left + "px",
                    "display": "block"
                });
            }
        },
        _contentAppend: function (elem) {
            if (ui.core.isDomObject(elem)) {
                elem = $(elem);
            } else if (!ui.core.isJQueryObject(elem)) {
                return;
            }
            this.contentPanel.append(elem);
            contentHeight += elem.height();
        },
        buttonAppend: function (elem) {
            if (ui.core.type(elem) === "string") {
                elem = $("#" + elem);
            } else if (ui.core.isDomObject(elem)) {
                elem = $(elem);
            } else if (!ui.core.isJQueryObject(elem)) {
                return;
            }
            var ctrlForm = this.buttonPanel.find(".ctrl-form");
            if (ctrlForm.length == 0) {
                ctrlForm = $("<div class='ctrl-form' />");
                this.buttonPanel.append(ctrlForm);
            }
            ctrlForm.append(elem);
        },
        append: function (elem) {
            if (!elem.jquery) {
                elem = $(elem);
            }
            this.panel.html("");
            this.panel.append(elem);
        },
        show: function () {
            var that = this;
            if (!this.animating && !this.isShow) {
                var result = this.fire(showing);
                if (result === false) return;

                this.animating = true;
                this.panel.css("display", "block");
                this.panel.animate(
                    {
                        "left": this.left + "px",
                        "opacity": 1,
                        "filter": "Alpha(opacity=1)"
                    },
                    240, "swing",
                    function () {
                        that.animating = false;
                        that.isShow = true;
                        that.fire(showed);
                    }
                );
            }
        },
        hide: function () {
            var that = this;
            var flag;
            if (!this.animating && this.isShow) {
                var result = this.fire(hiding);
                if (result === false) return;

                this.animating = true;
                this.panel.animate(
                    {
                        "left": this.hideLeft + "px",
                        "opacity": 0,
                        "filter": "Alpha(opacity=0)"
                    },
                    240, "swing",
                    function () {
                        that.animating = false;
                        that.isShow = false;
                        that.panel.css("display", "none");
                        that.fire(hided);
                    }
                );
            }
        }
    });

    $.fn.toCtrlPanel = function (option) {
        if (!this || this.length == 0 || this.nodeName() !== "DIV") {
            return null;
        }
        var error = new Error("parent is null");
        if (!option.parent)
            throw error;
        if (ui.core.type(option.parent) === "string") {
            option.parent = $("#" + option.parent);
            if (option.parent.length == 0) {
                throw error;
            }
        }

        return ctrlPanel(option, this);
    };

})(jQuery);